package com.dkh.recommend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dkh.recommend.dto.Result;
import com.dkh.recommend.dto.UserDTO;
import com.dkh.recommend.entity.TbMusic;
import com.dkh.recommend.entity.TbPlaylist;
import com.dkh.recommend.entity.TbRelate;
import com.dkh.recommend.entity.TbUser;
import com.dkh.recommend.mapper.TbPlaylistMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dkh.recommend.mapper.TbRelateMapper;
import com.dkh.recommend.service.ITbCollectService;
import com.dkh.recommend.service.ITbMusicService;
import com.dkh.recommend.service.ITbPlaylistService;
import com.dkh.recommend.utils.RecScoreUtils;
import com.dkh.recommend.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.dkh.recommend.utils.RedisConstants.PLAY_LIST_KEY;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author dkh
 * @since 2022-12-14
 */
@Slf4j
@Service
@Transactional
public class TbPlaylistServiceImpl extends ServiceImpl<TbPlaylistMapper, TbPlaylist> implements ITbPlaylistService {

    private ITbCollectService collectService;

    private ITbMusicService musicService;

    @Autowired
    private TbRelateMapper relateMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

//  根据构造器注入依赖，防止循环依赖
    public TbPlaylistServiceImpl(ITbCollectService collectService, ITbMusicService musicService) {
        this.collectService = collectService;
        this.musicService = musicService;
    }

    /**
     * 获取当前用户的播放列表
     * @return
     */
    @Override
    public Result getmyplaylist() {
        //        从locolhost中获取用户id
        Long userId = UserHolder.getUser().getUserId();

//        redis缓存的key
        String key = PLAY_LIST_KEY+userId;
//        1.判断当前用户播放列表是否在redis有缓存
//        List<String> playList_Redis = stringRedisTemplate.opsForList().range(key, 0, -1);
//      playList存入map
        Set<String> playList_set = stringRedisTemplate.opsForSet().members(key);

//        1.1判断缓存是否存在
//        if (playList_Redis != null && playList_Redis.size()>0){
////            2.缓存存在直接返回
//            List<TbPlaylist> tbPlaylist_s = new ArrayList<>();
//          playList_Redis.stream().forEach(playList-> {
//              TbPlaylist tbPlaylist = JSONUtil.toBean(playList, TbPlaylist.class);
//              tbPlaylist_s.add(tbPlaylist);
//          });
//
//          return Result.ok(tbPlaylist_s);
//        }
        if ( !playList_set.isEmpty() && playList_set.size() > 0){
//            2.缓存存在直接返回
            List<TbPlaylist> tbPlaylist_s = new ArrayList<>();
//        有缓存集合
//            解析集合set,加入List<TbPlaylist> tbPlaylist_s
//            List<Long> ids1 = playList_set.stream().map(Long::valueOf).collect(Collectors.toList());
            playList_set.stream().forEach(tbPlaylist->{
                TbPlaylist tbPlaylist1 = JSONUtil.toBean(tbPlaylist, TbPlaylist.class);
                tbPlaylist_s.add(tbPlaylist1);
            });


            return Result.ok(tbPlaylist_s);
        }

//        3.若无缓存则查询数据库
//          4.根据条件wrapper查询数据库
        LambdaQueryWrapper<TbPlaylist> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TbPlaylist::getUserId,userId);
        List<TbPlaylist> myPlaylists = list(queryWrapper);
//        5.将数据存入redis
//        5.1将查询数据库表获取到的对象列表转为json列表并存入redis缓存
        myPlaylists.stream().forEach(myPlaylist->{
//            stringRedisTemplate.opsForList().leftPush(key,JSONUtil.toJsonStr(myPlaylist));
            stringRedisTemplate.opsForSet().add(key,JSONUtil.toJsonStr(myPlaylist));
        });
        return Result.ok(myPlaylists);
    }

    /**
     * 添加音乐到播放列表
     * @param tbMusic
     * @return
     */
    @Override
    public Result add2PlayList(TbMusic tbMusic) {

        Long userId = UserHolder.getUser().getUserId();


//        将音乐存入到播放列表
        TbPlaylist tbPlaylist = BeanUtil.toBean(tbMusic, TbPlaylist.class);
        tbPlaylist.setUserId(userId);

//        先判断当前播放列表中是否已经存在该音乐（去重复）
        LambdaQueryWrapper<TbPlaylist> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TbPlaylist::getUserId,userId)
                .eq(TbPlaylist::getMusicId,tbMusic.getMusicId());
        List<TbPlaylist> list = this.list(wrapper);
//        判断是否存在
        if (!list.isEmpty() || list.size() > 0){
          return   Result.fail("列表中已经存在！");
        }


//        将音乐存入到播放列表
        boolean save2play = save(tbPlaylist);
        if (!save2play){
            Result.fail("添加播放列表失败！");
        }
        //        redis缓存的key
        String key = PLAY_LIST_KEY+userId;
//        将redis缓存删除,保持数据统一
        stringRedisTemplate.delete(key);

//        加入播放列表+1分
        TbRelate relate = new TbRelate();
        relate.setMusicId(tbMusic.getMusicId());
        relate.setUserId(userId);
        relate.setIndex(1);
        RecScoreUtils.addScore(relate,relateMapper);


        return Result.ok();
    }

    /**
     * 添加多个音乐到播放列表
     * @param musicList
     * @return
     */
    @Override
    public Result add2playList2(List<TbMusic> musicList) {
        Long userId = UserHolder.getUser().getUserId();
        //        将音乐存入到播放列表
        List<TbPlaylist> tbPlaylists = BeanUtil.copyToList(musicList, TbPlaylist.class);
        saveBatch(tbPlaylists);

        //        redis缓存的key
        String key = PLAY_LIST_KEY+userId;
//        将redis缓存删除,保持数据统一
        stringRedisTemplate.delete(key);
        return Result.ok();
    }

    /**
     * 删除播放列表内的某一音乐
     * @param musicId
     * @return
     */
    @Override
    public Result delete2PlayList(String musicId) {
//        获取当前登陆用户的Id
        Long userId = UserHolder.getUser().getUserId();
        Long musicIdL = Long.valueOf(musicId);
        LambdaQueryWrapper<TbPlaylist> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TbPlaylist::getUserId,userId)
                .eq(TbPlaylist::getMusicId,musicIdL);
        boolean b = this.remove(wrapper);

        if (!b){
            return Result.fail("移除失败！");
        }
        //        redis缓存的key
        String key = PLAY_LIST_KEY+userId;
//        将redis缓存删除,保持数据统一
        stringRedisTemplate.delete(key);

//        手动从播放列表减去扣分
        TbRelate relate = new TbRelate();
        relate.setMusicId(musicIdL);
        relate.setUserId(userId);
        relate.setIndex(1);
        RecScoreUtils.decScore(relate,relateMapper);



        return Result.ok();

    }

    /**
     * 删除当前用户下的所有播放列表
     * @return
     */
    @Override
    public Result deleteAll2PlayList() {

//        获取当前用户id
        Long userId = UserHolder.getUser().getUserId();
        LambdaQueryWrapper<TbPlaylist> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TbPlaylist::getUserId,userId);
        boolean remove1 = remove(queryWrapper);
        if (!remove1){
            return Result.fail("清空播放列表失败！");
        }

        //        redis缓存的key
        String key = PLAY_LIST_KEY+userId;
//        将redis缓存删除,保持数据统一
        stringRedisTemplate.delete(key);


        return Result.ok();
    }

    /**
     * 根据收藏夹id，将收藏夹id的收藏夹音乐添加到播放列表
     * @param collectId
     * @return
     */
    @Override
    @Transactional
    public Result Collect2playlist(String collectId) {
//        用户id
        Long userId = UserHolder.getUser().getUserId();

        Long collectId2L  = Long.valueOf(collectId);
//        1.根据收藏夹id获取收藏夹的音乐ids列表
        List<Long> MusicIds = (List<Long>) collectService.GetCollectMusicIds(collectId2L).getData();
//            根据音乐ids获取音乐
        List<TbMusic> musicList = musicService.listByIds(MusicIds);
//        将获取到的音乐列表保存到播放列表
        List<TbPlaylist> tbPlaylists = BeanUtil.copyToList(musicList, TbPlaylist.class);
//        根据用户id删除播放列表
        LambdaQueryWrapper<TbPlaylist> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TbPlaylist::getUserId,userId);
        this.remove(wrapper);

//        将userId加入tbPlayList
        tbPlaylists.stream().forEach(tbPlaylist -> {
            tbPlaylist.setUserId(userId);
        });
//        保存
        this.saveBatch(tbPlaylists);


        //        redis缓存的key
        String key = PLAY_LIST_KEY+userId;
//        将redis缓存删除,保持数据统一
        stringRedisTemplate.delete(key);
        return Result.ok();
    }




}
